import datetime
from decimal import *
from math import ceil
from django.db import models
from django.db.models import Sum
from django.db.models import F
from django.utils import timezone
from core.tools.mysql_connect import SqlModel


class PriceUpdateManager(models.Manager, SqlModel):
    def create_price(self, channel_product_obj, base_record=None, update_time=None):
        """
        根据之前的记录修改价格
        :param channel_product_obj:  产品对象
        :param base_record:  之前的记录对象
        :param update_time:  更新时间
        :return:
        """
        if base_record:
            result = self.create(
                reserved_b=base_record.reserved_b,
                level1=base_record.level1,
                level2=base_record.level2,
                level3=base_record.level3,
                price_type=channel_product_obj.product.price_type,
                channel_product=channel_product_obj
            )
        else:
            result = self.create(
                reserved_b=0,
                level1=0,
                level2=0,
                level3=0,
                price_type=channel_product_obj.product.price_type,
                channel_product=channel_product_obj
            )
        if update_time:
            result.update_time = update_time
            result.save()

    def get_price_list(self, channel, product_name=None):
        """
        获取价格列表
        :param channel:
        :param product_name:
        :return:
        """
        if product_name:
            sql = "SELECT DISTINCT `order_priceupdate`.`channel_product_id` FROM `order_priceupdate` INNER JOIN `sales_man_channelproduct` ON (`order_priceupdate`.`channel_product_id` = `sales_man_channelproduct`.`id`) INNER JOIN `product_product` ON (`sales_man_channelproduct`.`product_id` = `product_product`.`id`) WHERE (`sales_man_channelproduct`.`channel_id` = {0} AND `sales_man_channelproduct`.`status` = True AND `product_product`.`name` LIKE BINARY '%{1}%' AND `product_product`.`status` = True AND `product_product`.`is_pay` = True) ORDER BY `order_priceupdate`.`update_time` DESC".format(
                channel.id, product_name)
        else:
            sql = "SELECT DISTINCT `order_priceupdate`.`channel_product_id` FROM `order_priceupdate` INNER JOIN `sales_man_channelproduct` ON (`order_priceupdate`.`channel_product_id` = `sales_man_channelproduct`.`id`) INNER JOIN `product_product` ON (`sales_man_channelproduct`.`product_id` = `product_product`.`id`) WHERE (`sales_man_channelproduct`.`channel_id` = %s AND `sales_man_channelproduct`.`status` = True AND `product_product`.`status` = True AND `product_product`.`is_pay` = True) ORDER BY `order_priceupdate`.`update_time` DESC" % channel.id
        print(sql)
        self.cursor.execute(sql)
        distinct_data = self.cursor.fetchall()  # 获取查询的所有记录
        data_list = []
        now_time = datetime.date.today()
        delta = datetime.timedelta(days=1)
        now_time += delta
        for i in distinct_data:
            result_base = self.filter(channel_product__channel=channel, channel_product__status=True,
                                      channel_product_id=i[0])
            gt_update = result_base.filter(update_time__lt=now_time)
            if gt_update.exists():
                data_list.append(gt_update.first().id)
            else:
                data_list.append(result_base.first().id)
        return data_list


class PriceUpdate(models.Model):
    """
    价钱记录表
    """
    PRICE_TYPE = ((1, "固定金额"), (2, "百分比"),)
    channel_product = models.ForeignKey("sales_man.ChannelProduct", verbose_name="产品渠道表", blank=True, null=True)
    sum_price = models.DecimalField(verbose_name="总佣金", max_digits=9, decimal_places=5, default=0,
                                    help_text="自行换算成小数(如果是百分比)")
    reserved = models.DecimalField(verbose_name="预留价格", max_digits=9, decimal_places=5, default=0,
                                   help_text="自行换算成小数(如果是百分比)")
    reserved_b = models.DecimalField(verbose_name="预留比例", max_digits=5, decimal_places=2, default=0,
                                     help_text="自行换算成小数(如果是百分比)")
    level1 = models.DecimalField(max_digits=9, decimal_places=5, default=0, verbose_name="客户百分比",
                                 help_text="请换算成小数", null=True)
    level2 = models.DecimalField(max_digits=9, decimal_places=5, default=0, verbose_name="上级百分比",
                                 help_text="请换算成小数", null=True)
    level3 = models.DecimalField(max_digits=9, decimal_places=5, default=0, verbose_name="上上级百分比",
                                 help_text="请换算成小数", null=True)
    price = models.DecimalField(max_digits=9, decimal_places=5, default=0, verbose_name="客户价格",
                                help_text="如果是百分比，请换算成小数", blank=True, null=True)
    leader_price = models.DecimalField(max_digits=9, decimal_places=5, default=0, verbose_name="上级获得",
                                       help_text="百分比，请换算成小数", blank=True, null=True)
    leader_leader_price = models.DecimalField(max_digits=9, decimal_places=5, default=0, verbose_name="上上级获得",
                                              help_text="百分比，请换算成小数", blank=True, null=True)
    price_type = models.IntegerField(choices=PRICE_TYPE, verbose_name="价格类型", default=1)
    update_time = models.DateTimeField(default=timezone.now, verbose_name="更新时间")
    objects = PriceUpdateManager()

    class Meta:
        ordering = ["-update_time"]
        verbose_name = "佣金记录表"
        verbose_name_plural = verbose_name

    def __str__(self):
        return "%s,%s:%s" % (self.channel_product.channel.name, self.channel_product.product.name, self.price)

    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        sum_price = self.channel_product.sum_price
        self.sum_price = sum_price
        if isinstance(self.sum_price, Decimal):
            sum_price = float(sum_price)
        if isinstance(self.reserved_b, Decimal):
            reserved_b = float(self.reserved_b)
            level1 = float(self.level1)
            level2 = float(self.level2)
            level3 = float(self.level3)
        else:
            reserved_b = self.reserved_b
            level1 = self.level1
            level2 = self.level2
            level3 = self.level3
        if self.channel_product.product.price_type == 1:
            reserved = round(reserved_b * sum_price, 2)
            price = round(level1 * sum_price, 2)
            leader_price = round(level2 * sum_price, 2)
            leader_leader_price = round(level3 * sum_price, 2)
        else:
            reserved = round(reserved_b * sum_price, 5)
            price = round(level1 * sum_price, 5)
            leader_price = round(level2 * sum_price, 5)
            leader_leader_price = round(level3 * sum_price, 5)
        self.reserved = reserved
        self.price = price
        self.leader_price = leader_price
        self.leader_leader_price = leader_leader_price
        self.price_type = self.channel_product.product.price_type
        super(PriceUpdate, self).save()


class BaseOrderManager(models.Manager):
    def insert_order(self, single, create_time, cash=None):
        """
        插入数据
        :param create_time: 成交时间
        :param single: 标识
        :param cash: 金额  如果是贷款类（保险类）的产品，就需要知道贷了多少钱，而且类型是百分比
        :return:
        """
        channel = single.b_user.channel
        salesman = single.b_user  # 谁申请的产品给谁钱
        price_qs = PriceUpdate.objects.filter(channel_product__channel=channel,
                                              channel_product__product=single.product)
        now_time = datetime.date.today()
        delta = datetime.timedelta(days=1)
        now_time += delta
        price_obj = price_qs.filter(update_time__lt=now_time).first()
        if salesman.tel != single.applicant.tel:
            # 如果申请信息和注册用户信息不是同一个人 就用推荐人的价格
            price = price_obj.leader_price
        else:
            # 如果申请信息和注册用户信息是同一个人 就用客户价格
            price = price_obj.price
        # price = PriceUpdate.objects.filter(product=single.product).first()
        if cash and price_obj.price_type == 2:  # 贷款类产品
            income = cash * price.price
        elif not cash and price_obj.price_type == 1:  # 信用卡类产品，手填固定值
            income = price
        else:
            raise Exception("请检查产品金额类型")
        order, created = self.get_or_create(
            product=single.product,
            salesman=salesman,
            single=single,
            price=price_obj,
            income=income,
            create_time=create_time,
        )
        order.is_close = 2
        order.save()
        if created:
            TeamInCome.objects.insert_order(order, cash=cash)

    def sum_income(self, salesman, p_id=None):
        """
        已提现，可提现，待提现 数量
        :return:
        """
        info = self.filter(salesman=salesman)
        if p_id:
            info = info.filter(product_id=p_id)
        sum_is_close_1 = info.filter(is_close=1).aggregate(sum_is_close_1=Sum("income")).get("sum_is_close_1")
        sum_is_close_2 = info.filter(is_close=2).aggregate(sum_is_close_2=Sum("income")).get("sum_is_close_2")
        sum_is_close_3 = info.filter(is_close=3).aggregate(sum_is_close_3=Sum("income")).get("sum_is_close_3")
        sum_is_close_1 = sum_is_close_1 if sum_is_close_1 else 0
        sum_is_close_2 = sum_is_close_2 if sum_is_close_2 else 0
        sum_is_close_3 = sum_is_close_3 if sum_is_close_3 else 0
        return {
            "sum_is_close_1": sum_is_close_1,
            "sum_is_close_2": sum_is_close_2,
            "sum_is_close_3": sum_is_close_3
        }

    def __order_close_type(self, salesman, is_close=None):
        info = self.filter(salesman=salesman)
        if is_close:
            info = info.filter(is_close=is_close)
        return info

    def id_list_and_close_sum(self, salesman, is_close=2):
        info = self.__order_close_type(salesman, is_close=is_close)
        amount = info.aggregate(is_close=Sum("income")).get("is_close")
        amount = amount if amount else 0
        amount = float(amount) * 100
        amount = ceil(amount)  # 分
        id_list = info.values_list('id', flat=True)
        return id_list, amount

    def update_close(self, id_list):
        if id_list:
            self.filter(id__in=id_list).update(is_close=1)


class BaseOrder(models.Model):
    """
    个人订单（因为有提现的状态，所以只能是一个用户产生了订单，分三个订单即自己，上级，上上级）
    """
    CLOSE_TYPE = ((1, "已提现"), (2, "可提现"), (3, "待提现"))
    single = models.ForeignKey("sales_man.Single", verbose_name="申请标识", db_index=True)
    salesman = models.ForeignKey('sales_man.SalesMan', verbose_name="直推业务员", help_text="有可能是自己，也有可能是上级")
    product = models.ForeignKey('product.Product', verbose_name="产品")
    price = models.ForeignKey("PriceUpdate", verbose_name="价格")
    create_time = models.DateTimeField(verbose_name="创建时间(银行返回的时间)")
    income = models.DecimalField(verbose_name="收益", max_digits=7, decimal_places=2, default=0)
    is_close = models.IntegerField(verbose_name="结算状态", default=2, choices=CLOSE_TYPE, db_index=True)
    close_time = models.DateTimeField(verbose_name="结算日期", blank=True, null=True)
    objects = BaseOrderManager()

    class Meta:
        verbose_name = "订单表"
        verbose_name_plural = verbose_name

    def __str__(self):
        return "%s:%s:%s" % (self.salesman.name, self.product.name, self.income)


class TeamInComeManager(models.Manager):
    def update_close(self, id_list):
        if id_list:
            self.filter(id__in=id_list).update(is_close=1)

    def __insert_order(self, income, order, leader, level):
        """
        插入数据
        :param income:
        :param order:
        :param leader:
        :param level: 增加一个标记，是由自己下面几级带来的效益
        :return:
        """
        return self.create(
            income=income,
            salesman=leader,
            order=order,
            level=level,
            create_time=order.create_time,
            is_close=2
        )

    def insert_order(self, self_order, cash=None):
        """
        个人订单
        分别判断是否有上级和上上级，如果有加入收益当中
        :param self_order: 自己的订单
        :param cash: 自己的订单
        :return:
        """
        # self_order = BaseOrder
        _leader = self_order.salesman.leader
        price_type = self_order.price.price_type
        if price_type == 1:
            income_leader = self_order.price.leader_price
        else:
            income_leader = float(cash) * float(self_order.price.leader_price)
        if price_type == 1:
            income_leader_leader = self_order.price.leader_leader_price
        else:
            income_leader_leader = float(cash) * float(self_order.price.leader_leader_price)

        if _leader:
            self.__insert_order(income_leader, self_order, _leader, 1)
            _leader_leader = _leader.leader
            if _leader_leader:
                self.__insert_order(income_leader_leader, self_order, _leader_leader, 2)
            else:
                self_order.income = F("income") + income_leader_leader
                self_order.save()
        else:
            self_order.income = F("income") + income_leader + income_leader_leader
            self_order.save()

    def all_order(self, salesman):
        """
        所有订单
        :param salesman:
        :return:
        """
        return self.filter(salesman=salesman)

    def sum_income(self, salesman, p_id=None):
        """
        已提现，可提现，待提现 数量
        :return:
        """
        info = self.filter(salesman=salesman)
        if p_id:
            info = info.filter(product_id=p_id)
        sum_is_close_1 = info.filter(is_close=1).aggregate(sum_is_close_1=Sum("income")).get("sum_is_close_1")
        sum_is_close_2 = info.filter(is_close=2).aggregate(sum_is_close_2=Sum("income")).get("sum_is_close_2")
        sum_is_close_3 = info.filter(is_close=3).aggregate(sum_is_close_3=Sum("income")).get("sum_is_close_3")
        sum_is_close_1 = sum_is_close_1 if sum_is_close_1 else 0
        sum_is_close_2 = sum_is_close_2 if sum_is_close_2 else 0
        sum_is_close_3 = sum_is_close_3 if sum_is_close_3 else 0
        return {
            "sum_is_close_1": sum_is_close_1,
            "sum_is_close_2": sum_is_close_2,
            "sum_is_close_3": sum_is_close_3
        }

    def __order_close_type(self, salesman, is_close=None):
        info = self.filter(salesman=salesman)
        if is_close:
            info = info.filter(is_close=is_close)
        return info

    def id_list_and_close_sum(self, salesman, is_close=2):
        info = self.__order_close_type(salesman, is_close=is_close)
        amount = info.aggregate(is_close=Sum("income")).get("is_close")
        amount = amount if amount else 0
        amount = float(amount) * 100
        amount = ceil(amount)  # 分
        id_list = info.values_list('id', flat=True)
        return id_list, amount


class TeamInCome(models.Model):
    """
    团队收入, 团队贡献
    用户 A给上级B带来的收益记录一条， 用户A给上上级C带来的收益记录一条
        salesman 指的是B 和 C
    """
    CLOSE_TYPE = ((1, "已提现"), (2, "可提现"), (3, "待提现"))
    LEVEL = ((1, "下级"), (2, "下下级"))
    salesman = models.ForeignKey('sales_man.SalesMan', verbose_name="自己")
    order = models.ForeignKey('BaseOrder', verbose_name="对应的订单")
    level = models.IntegerField(default=2, verbose_name="给我带来收益的级别", choices=LEVEL)
    income = models.DecimalField(verbose_name="收益", max_digits=7, decimal_places=2, default=0)
    is_close = models.IntegerField(verbose_name="结算状态", choices=CLOSE_TYPE, default=2)
    create_time = models.DateTimeField(verbose_name="创建时间(银行返回的时间)")
    objects = TeamInComeManager()

    class Meta:
        verbose_name = "团队收入"
        verbose_name_plural = verbose_name
        ordering = ["-create_time"]


class TransferErrorCodeManager(models.Manager):
    def create_data(self, info):
        """
        微信企业付款到零钱
        :param info:
        :return:
        """
        return self.create(
            partner_trade_no=info.get("partner_trade_no"),
            return_code=info.get("return_code"),
            return_msg=info.get("return_msg"),
            result_code=info.get("result_code"),
            err_code=info.get("err_code"),
            payment_no=info.get("payment_no"),
            payment_time=info.get("payment_time"),
            is_again=info.get("again"),
            err_code_des=info.get("err_code_des")
        )


class TransferErrorCode(models.Model):
    """
    微信企业付款错误代码
    """
    partner_trade_no = models.CharField(verbose_name="商户订单号", max_length=64, blank=True, null=True)
    return_code = models.CharField(verbose_name="返回状态码", max_length=32, blank=True, null=True, help_text="SUCCESS/FAIL")
    return_msg = models.CharField(verbose_name="返回信息", max_length=256, blank=True, null=True)
    # 以下字段在return_code为SUCCESS的时候有返回
    result_code = models.CharField(verbose_name="业务结果", max_length=64, blank=True, null=True)
    err_code = models.CharField(verbose_name="错误代码", max_length=64, blank=True, null=True)
    err_code_des = models.CharField(verbose_name="错误代码描述", max_length=130, blank=True, null=True)
    # 以下字段在return_code 和result_code都为SUCCESS的时候有返回
    payment_no = models.CharField(verbose_name="微信订单号", max_length=64, blank=True, null=True)
    payment_time = models.CharField(verbose_name="微信支付成功时间", max_length=64, blank=True, null=True)
    # 自定义 只有在出现SYSTEMERROR 系统繁忙，请稍后再试。 才会有此字段
    is_again = models.BooleanField(verbose_name="重试", default=False)
    objects = TransferErrorCodeManager()

    class Meta:
        verbose_name = "微信企业付款错误代码"
        verbose_name_plural = verbose_name

    def update_status(self, info):
        self.return_code = info.get("return_code")
        self.err_code = info.get("err_code")
        self.err_code_des = info.get("err_code_des")
        self.payment_no = info.get("payment_no")
        self.payment_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.save()


class TransferRecord(models.Model):
    """
    提现记录
    谁（salesman） 什么时候（create_time） 提现多少（amount），对应的订单，（self_income、team_income）
    1、查看可提现的数据，然后将数据取总 放到amount里，并将订单保存在self_income 和 team_income
    2、提现，
    3、查看提现状态，如果
    """
    salesman = models.ForeignKey('sales_man.SalesMan', verbose_name="用户")
    team_income = models.TextField(verbose_name="团队业绩", blank=True, null=True)
    self_income = models.TextField(verbose_name="个人业绩", blank=True, null=True)  # [team_id,team_id,]
    amount = models.IntegerField(verbose_name="金额")
    spbill_create_ip = models.CharField(verbose_name="IP地址", max_length=32)
    partner_trade_no = models.CharField(max_length=64, verbose_name="商户订单号")
    nonce_str = models.CharField(max_length=64, verbose_name="随机字符串")
    is_over = models.BooleanField(default=False, db_index=True, verbose_name="是否处理完", help_text="用于防止重复提交")
    create_time = models.DateTimeField(auto_now=True, verbose_name="创建时间")
    update_time = models.DateTimeField(auto_now_add=True, verbose_name="更新时间")
    # 对应的微信返回错误码
    error_code = models.OneToOneField("TransferErrorCode", verbose_name="对应的错误码", blank=True, null=True)

    class Meta:
        verbose_name = "提现记录"
        verbose_name_plural = verbose_name
